package com.restkeeper.controller.store;

import com.google.common.collect.Lists;
import com.restkeeper.dto.CurrentAmountCollectDTO;
import com.restkeeper.dto.CurrentHourCollectDTO;
import com.restkeeper.dto.DayAmountCollectDTO;
import com.restkeeper.dto.PrivilegeDTO;
import com.restkeeper.entity.OrderDetailAllView;
import com.restkeeper.entity.ReportDishEntity;
import com.restkeeper.service.*;
import com.restkeeper.vo.store.AmountCollectVO;
import com.restkeeper.vo.store.BarChartCollectVO;
import com.restkeeper.vo.store.PieVo;
import com.restkeeper.vo.store.PrivilegeVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Api(tags = { "报表" })
@RestController
@RequestMapping("/report")
public class ReportController {
    @Reference(version = "1.0.0", check=false)
    private IOrderService orderService;

    @Reference(version = "1.0.0", check=false)
    private IOrderDetailService orderDetailService;

    @Reference(version = "1.0.0", check=false)
    private IReportPayService reportPayService;

    @Reference(version = "1.0.0", check=false)
    private IReportDishService reportDishService;

    @Reference(version = "1.0.0",check = false)
    private IReportTimeService reportTimeService;

    @ApiOperation(value = "当日或日报获取销量数据")
    @GetMapping("/amountCollect/{date}")
    public AmountCollectVO getAmountCollect(@PathVariable String date){
        AmountCollectVO vo = new AmountCollectVO();

        LocalDate nowDate = LocalDate.now();
        LocalDate start = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate end = start.plusDays(1);

        //传入日期与当前日期相等，获取本日信息
        CurrentAmountCollectDTO dto = orderService.getCurrentCollect(start,end);
        BeanUtils.copyProperties(dto,vo);
        return vo;

    }

    @ApiOperation(value = "按日统计时段销售趋势，包含门店概况与营收概况")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "type", value = "类型(1:金额;2:数量)", required = true, dataType = "Int")})
    @GetMapping("/hourCollect/{type}/{date}")
    public BarChartCollectVO getHourCollect(@PathVariable Integer type,@PathVariable String date){
        LocalDate now = LocalDate.now();
        LocalDate start = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate end = start.plusDays(1);

        List<CurrentHourCollectDTO> dtos = Lists.newArrayList();
        dtos = orderService.getCurrentHourCollect(start,end,type);

        BarChartCollectVO vo = new BarChartCollectVO();
        dtos.forEach(d->{
            vo.getXAxis().add(d.getCurrentDateHour() + "");
            vo.getSeries().add(d.getTotalAmount());
        });

        return vo;
    }

    @ApiOperation(value = "按日获取菜品分类占比")
    @GetMapping("/categoryCollect/{type}/{date}")
    public List<PieVo> getCategoryAmountCollect(@PathVariable int type,@PathVariable String date){

        LocalDate now = LocalDate.now();
        LocalDate start = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate end = start.plusDays(1);

        //本日数据
        if (type == 1){

            return orderDetailService.getCurrentCategoryAmountCollect(start,end).stream().map(d->{
                PieVo pieVo = new PieVo();
                pieVo.setValue(d.getDishAmount());
                pieVo.setName(d.getDishCategoryName());
                return pieVo;
            }).collect(Collectors.toList());
        }

        if (type == 2){

            return orderDetailService.getCurrentCategoryCountCollect(now,end).stream().map(d->{
                PieVo pieVo = new PieVo();
                pieVo.setValue(d.getTotalCount());
                pieVo.setName(d.getDishCategoryName());
                return pieVo;
            }).collect(Collectors.toList());
        }
        return null;
    }

    @ApiOperation(value = "按日获取菜品销售排行")
    @GetMapping("/currentDishRank/{date}")
    public BarChartCollectVO getCurrentDishRank(@PathVariable String date){
        LocalDate now = LocalDate.now();
        LocalDate start = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate end = start.plusDays(1);

        BarChartCollectVO result = new BarChartCollectVO();

        //查询本日数据
        orderDetailService.getCurrentDishRank(start,end)
                .forEach(d->{
                    result.getXAxis().add(d.getDishName());
                    result.getSeries().add(d.getTotalCount());
                });
        return result;
    }

    @ApiOperation(value = "按日获取店内收款构成")
    @GetMapping("/payTypeCollect/{date}")
    public List<PieVo> getPayTypeCollect(@PathVariable String date){

        LocalDate now = LocalDate.now();
        LocalDate start = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate end = start.plusDays(1);

        List<PieVo> result = Lists.newArrayList();

        //本日数据
        result =orderService.getPayTypeCollect(start,end)
                .stream()
                .map(d-> {
                    //通过map将DTO转换成PieVo
                    PieVo pieVo = new PieVo();
                    pieVo.setName(d.getPayName());
                    pieVo.setValue(d.getTotalCount());
                    return pieVo;
                })
                .collect(Collectors.toList());

        return result;
    }

    @ApiOperation(value = "按日获取优惠指标数据")
    @GetMapping("/privilegeCollect/{date}")
    public PrivilegeVO getPrivilegeCollect(@PathVariable String date){

        PrivilegeVO privilegeVO = new PrivilegeVO();

        LocalDate now = LocalDate.now();
        LocalDate start = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate end = start.plusDays(1);

        PrivilegeDTO privilegeDTO = new PrivilegeDTO();

        privilegeDTO = orderService.getPrivilegeCollect(start, end);

        List<PieVo> pieVoList = Lists.newArrayList();
        double total = privilegeDTO.getPresentAmount() + privilegeDTO.getFreeAmount() + privilegeDTO.getSmallAmount();

        //赠菜
        PieVo present = new PieVo();
        present.setValue(privilegeDTO.getPresentAmount());
        present.setName("赠菜");
        if(privilegeDTO.getPresentAmount() == 0){
            present.setPercent(0.0);
        }else
        {
            present.setPercent(((double) privilegeDTO.getPresentAmount())/total * 100);
        }
        pieVoList.add(present);

        //免单
        PieVo free = new PieVo();
        free.setName("免单");
        free.setValue(privilegeDTO.getFreeAmount());
        if(privilegeDTO.getFreeAmount() == 0){
            free.setPercent(0.0);
        }else {
            free.setPercent(((double) privilegeDTO.getFreeAmount())/total * 100);
        }
        pieVoList.add(free);

        //抹零
        PieVo small = new PieVo();
        small.setName("抹零");
        small.setValue(privilegeDTO.getSmallAmount());
        if(privilegeDTO.getSmallAmount() == 0){
            small.setPercent(0.0);
        }else {
            small.setPercent(((double) privilegeDTO.getSmallAmount())/total * 100);
        }
        pieVoList.add(small);

        privilegeVO.setDataList(pieVoList);
        privilegeVO.setTotal(privilegeDTO.getPresentAmount() + privilegeDTO.getFreeAmount() + privilegeDTO.getSmallAmount());

        return privilegeVO;
    }





    @ApiOperation(value = "获取一定日期之内的销售数据汇总")
    @GetMapping("/dayCollect/{start}/{end}")
    public AmountCollectVO getDayCollect(@PathVariable String start,@PathVariable String end){

        AmountCollectVO vo = new AmountCollectVO();

        LocalDate nowDate = LocalDate.now();
        LocalDate startDate = LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endDate = LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE);

        //对比日期
        if (startDate.equals(endDate)){
            //日报
            if (startDate.equals(nowDate)){
                //查本日
                CurrentAmountCollectDTO dto = orderService.getCurrentCollect(nowDate,nowDate.plusDays(1));
                BeanUtils.copyProperties(dto,vo);
                return vo;
            }

            //传入日期与当前日期不等，按传入日期查询
            CurrentAmountCollectDTO dto = reportPayService.getDateAmount(startDate,startDate.plusDays(1));
            BeanUtils.copyProperties(dto,vo);
            return vo;
        }

        return null;
    }


    @ApiOperation(value = "获取一定日期之内的时段销售趋势")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "type", value = "1:按金额；2:按单数", required = true, dataType = "Int"),
            @ApiImplicitParam(paramType = "path", name = "start", value = "开始日期", required = true, dataType = "String"),
            @ApiImplicitParam(paramType = "path", name = "end", value = "结束日期", required = true, dataType = "String"),
    })
    @GetMapping("/dayAmountCollect/{type}/{start}/{end}")
    public BarChartCollectVO getDayAmountCollect(@PathVariable int type,@PathVariable String start,@PathVariable String end){

        LocalDate nowDate = LocalDate.now();
        LocalDate startDate = LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endDate = LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE);

        BarChartCollectVO vo = new BarChartCollectVO();
        List<CurrentHourCollectDTO> dtos = Lists.newArrayList();

        if (startDate.equals(endDate)){
            //日报
            if (nowDate.equals(startDate)){
                dtos = orderService.getCurrentHourCollect(nowDate,nowDate.plusDays(1),type);
            }else {
                //不是当日数据
                dtos = reportTimeService.getDateHourCollect(startDate, type);
            }

            dtos.forEach(d->{
                vo.getXAxis().add(d.getCurrentDateHour() + "");
                vo.getSeries().add(d.getTotalAmount());
            });

            return vo;
        }else {
            //周报或月报
            List<DayAmountCollectDTO> results = reportPayService.getDayAmountCollect(startDate,endDate);

            DateTimeFormatter formatters = DateTimeFormatter.ofPattern("MM月dd日");

            if(type == 1){
                vo.setXAxis(results.stream().map(r->r.getDate().format(formatters)).collect(Collectors.toList()));
                vo.setSeries(results.stream().map(r->r.getTotalAmount()).collect(Collectors.toList()));
            }
            if(type == 2){
                vo.setXAxis(results.stream().map(r->r.getDate().getDayOfMonth()+"").collect(Collectors.toList()));
                vo.setSeries(results.stream().map(r->r.getTotalCount()).collect(Collectors.toList()));
            }

            return vo;
        }
    }

    @ApiOperation(value = "获取时间范围之内的各种支付类型数据汇总")
    @GetMapping("/datePayTypeCollect/{start}/{end}")
    public List<PieVo> getDatePayTypeCollect(@PathVariable String start,@PathVariable String end){

        LocalDate now = LocalDate.now();
        LocalDate startDate = LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endDate = LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE);

        if (startDate.equals(endDate)){
            //日报
            List<PieVo> result = Lists.newArrayList();

            //本日数据
            if (now.equals(startDate)){
                result =orderService.getPayTypeCollect(now,now.plusDays(1))
                        .stream()
                        .map(d-> {
                            //通过map将DTO转换成PieVo
                            PieVo pieVo = new PieVo();
                            pieVo.setName(d.getPayName());
                            pieVo.setValue(d.getTotalCount());
                            return pieVo;
                        })
                        .collect(Collectors.toList());

            }else {
                //非本日数据
                result = reportPayService
                        .getPayTypeCollect(startDate,startDate)
                        .stream()
                        .map(d->{
                            PieVo pieVo = new PieVo();
                            pieVo.setName(d.getPayName());
                            pieVo.setValue(d.getTotalCount());
                            return pieVo;
                        }).collect(Collectors.toList());
            }
            return result;
        }else {
            //周报或月报
            return reportPayService
                    .getPayTypeCollect(startDate,endDate)
                    .stream()
                    .map(d->{
                        PieVo pieVo = new PieVo();
                        pieVo.setName(d.getPayName());
                        pieVo.setValue(d.getTotalCount());
                        return pieVo;
                    }).collect(Collectors.toList());
        }
    }

    @ApiOperation(value = "获取时间范围之内的菜品类别销售汇总")
    @GetMapping("/dateCategoryCollect/{type}/{start}/{end}")
    public List<PieVo> getDateCategoryCollect(@PathVariable int type,@PathVariable String start,@PathVariable String end){
        LocalDate now = LocalDate.now();
        LocalDate startDate = LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endDate = LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE);

        if (startDate.equals(endDate)){
            //日报
            //本日数据
            if (now.equals(startDate)){
                Stream<OrderDetailAllView> stream = orderDetailService.getCurrentCategoryAmountCollect(now, now.plusDays(1)).stream();
                if (type == 1){
                    return stream.map(d->{
                        PieVo pieVo = new PieVo();
                        pieVo.setValue(d.getDishAmount());
                        pieVo.setName(d.getDishCategoryName());
                        return pieVo;
                    }).collect(Collectors.toList());
                }
                if (type == 2){
                    Stream<OrderDetailAllView> stream1 = orderDetailService.getCurrentCategoryCountCollect(now, now.plusDays(1)).stream();
                    return stream1.map(d->{
                        PieVo pieVo = new PieVo();
                        pieVo.setValue(d.getTotalCount());
                        pieVo.setName(d.getDishCategoryName());
                        return pieVo;
                    }).collect(Collectors.toList());
                }
            }else {
                //非当日数据
                Stream<ReportDishEntity> stream = reportDishService.getCategoryAmountCollect(startDate, startDate).stream();
                if(type == 1){
                    return stream.map(d->{
                        PieVo pieVo = new PieVo();
                        pieVo.setValue(d.getDishMoney());
                        pieVo.setName(d.getCategory());
                        return pieVo;
                    }).collect(Collectors.toList());

                }else if(type == 2){
                    return stream.map(d->{
                        PieVo pieVo = new PieVo();
                        pieVo.setValue(d.getDishNumber());
                        pieVo.setName(d.getCategory());
                        return pieVo;
                    }).collect(Collectors.toList());
                }
            }

        }else {
            //周报月报
            Stream<ReportDishEntity> stream = reportDishService.getCategoryAmountCollect(startDate, endDate).stream();
            if(type == 1){
                return stream.map(d->{
                    PieVo pieVo = new PieVo();
                    pieVo.setValue(d.getDishMoney());
                    pieVo.setName(d.getCategory());
                    return pieVo;
                }).collect(Collectors.toList());

            }else if(type == 2){
                return stream.map(d->{
                    PieVo pieVo = new PieVo();
                    pieVo.setValue(d.getDishNumber());
                    pieVo.setName(d.getCategory());
                    return pieVo;
                }).collect(Collectors.toList());
            }
        }

        return null;
    }

    @ApiOperation(value = "获取时间范围之内的菜品销售排行")
    @GetMapping("/dishRankForDate/{start}/{end}")
    public BarChartCollectVO getDishRank(@PathVariable String start,@PathVariable String end){

        LocalDate now = LocalDate.now();
        LocalDate startDate = LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endDate = LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE);

        BarChartCollectVO result = new BarChartCollectVO();

        if (endDate.equals(startDate)){
            //日报
            if (now.equals(startDate)){
                //查询本日数据
                orderDetailService.getCurrentDishRank(now,now.plusDays(1))
                        .forEach(d->{
                            result.getXAxis().add(d.getDishName());
                            result.getSeries().add(d.getTotalCount());
                        });
            }else {
                //查询非本日数据
                reportDishService
                        .getDishRank(startDate,startDate)
                        .forEach(d->{
                            result.getXAxis().add(d.getDishName());
                            result.getSeries().add(d.getDishNumber());
                        });
            }
        }else {
            //周月报
            reportDishService
                    .getDishRank(startDate,endDate)
                    .forEach(d->{
                        result.getXAxis().add(d.getDishName());
                        result.getSeries().add(d.getDishNumber());
                    });
        }
        return result;
    }

    @ApiOperation(value = "获取时间范围之内的优惠指标汇总数据")
    @GetMapping("/privilegeByDate/{start}/{end}")
    public PrivilegeVO getPrivilegeByDate(@PathVariable String start,@PathVariable String end){
        LocalDate now = LocalDate.now();
        LocalDate startDate = LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endDate = LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE);

        PrivilegeDTO dto = new PrivilegeDTO();

        if (endDate.equals(startDate)){
            //日报
            if (now.equals(startDate)){
                dto = orderService.getPrivilegeCollect(now, now.plusDays(1));
            }else {
                //非本日数据
                dto = reportPayService.getPrivilegeCollectByDate(startDate,startDate);
            }
        }else {
            //周报或月报
            dto = reportPayService.getPrivilegeCollectByDate(startDate,endDate);
        }

        List<PieVo> pieVoList = Lists.newArrayList();
        double total = dto.getPresentAmount() + dto.getFreeAmount() + dto.getSmallAmount();

        PieVo present = new PieVo();
        present.setValue(dto.getPresentAmount());
        present.setName("赠菜");
        if(dto.getPresentAmount() == 0){
            present.setPercent(0.0);
        }else
        {
            present.setPercent(((double) dto.getPresentAmount())/total * 100);
        }
        pieVoList.add(present);

        PieVo free = new PieVo();
        free.setName("免单");
        free.setValue(dto.getFreeAmount());
        if(dto.getFreeAmount() == 0){
            free.setPercent(0.0);
        }else {
            free.setPercent(((double) dto.getFreeAmount())/total * 100);
        }
        pieVoList.add(free);

        PieVo small = new PieVo();
        small.setName("抹零");
        small.setValue(dto.getSmallAmount());
        if(dto.getSmallAmount() == 0){
            small.setPercent(0.0);
        }else {
            small.setPercent(((double) dto.getSmallAmount())/total * 100);
        }
        pieVoList.add(small);

        PrivilegeVO vo = new PrivilegeVO();
        vo.setDataList(pieVoList);
        vo.setTotal(dto.getPresentAmount() + dto.getFreeAmount() + dto.getSmallAmount());


        return vo;
    }
}
